package tagcapturer;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.Vector;

import javax.swing.table.DefaultTableModel;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;

import epcglobal.ale.ECReport;
import epcglobal.ale.ECReportGroup;
import epcglobal.ale.ECReportGroupListMember;
import epcglobal.ale.ECReports;

class ClientWorker implements Runnable {
    private Socket client;
    private Viewer viewer;
    
    ClientWorker(Socket client, Viewer viewer) {
        this.client = client;
        this.viewer=viewer;
    }
    
    public void  run(){
      
        try {
            InputStream is = client.getInputStream();
            JAXBContext jc = JAXBContext.newInstance("epcglobal.ale");
            Unmarshaller u = jc.createUnmarshaller();
            JAXBElement element = (JAXBElement) u.unmarshal(is);
            ECReports reports = (ECReports) element.getValue();
            
            String specName=reports.getSpecName();
            
            View view=(View) viewer.getViews().get(specName);
            System.out.println("Capture URL: " + viewer.getCaptureUrl());
            // bravo debug:
            System.out.println("Spec name: "+ reports.getSpecName());
            System.out.println("ECSpec: " + reports.getECSpec());
            
            // end of bravo debug
            
            CaptureEventGenerator ceg = new CaptureEventGenerator(viewer.getCaptureUrl());
            
            // switch view if the alarm is set
            if (view!=null && view.isAlarm()) {
                viewer.setView(specName);
            }
            
            String reportSet=null;
//            if (view!=null){
//                System.out.println("View is not null");
//                System.out.println("ReportSet: " + view.getReportSet());
//            }else{
//                System.out.println("View is null");
//            }
            
            
            switch (view.getReportSet()) {
                case View.CURRENT:
                    reportSet="Current";
                    break;
                case View.ADDITIONS:
                    reportSet="Additions";
                    break;
                case View.DELETIONS:
                    reportSet="Deletions";
                    break;
            }

            DefaultTableModel tableModel;
            Vector tagVector;            
            int viewRowId;
            int mainViewRowId;

            // clear history
            tableModel= (DefaultTableModel) view.getTableModel();
            tagVector = (Vector) tableModel.getDataVector();

            for (int row=0; row<tagVector.size(); row++) {
                Vector tag = (Vector) tagVector.elementAt(row);
                int history = ((Integer) tableModel.getValueAt(row,5)).intValue();
                tableModel.setValueAt(history+1,row,5);
            }
            
            
            for (ECReport report : reports.getReports().getReport()) {
                for (ECReportGroup reportGroup : report.getGroup()) {
                    for (ECReportGroupListMember reportGroupListMember : reportGroup.getGroupList().getMember()) {
                    	//PEGA TAG ID AQUI FDP:
                    	String tagID = reportGroupListMember.getTag().getValue();
                        String epcisStatus = "N/A";
                        this.viewer.getDebuger().log("-- Captura -- ");
                        this.viewer.getDebuger().log("---- Tag    : " + tagID);
                        this.viewer.getDebuger().log("---- Leitor :  " + view.getReaders());
                        this.viewer.getDebuger().log("---- Spec   :  " + reports.getSpecName());
                        // chama web service
                        OpenbravoWS ws = new OpenbravoWS(this.viewer.getDebuger());
                        ws.notifyTagCaptureEvent(tagID, view.getReaders());
                       
                       //Send to EPCIS
                       if (view.isEpcisEnabled()){
                            //send to EPCIS for new Tag
                            //assume all events are of type OBSERVE
                            CaptureEvent ex = new CaptureEvent();
                            ex.setDescription("A tag has passed a reader");
                            ex.setType(0);
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
                            sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
                            Date currentTime = new Date();
                            String eventDateTime = sdf.format(currentTime);
                            System.out.println("GMT Event Time = " + eventDateTime);
                            ex.setEventTime(eventDateTime);
                            ex.setAction(1);
                            ex.setBizStep("urn:epcglobal:epcis:bizstep:fmcg:development");
                            ex.setBizLocation("urn:cuhk:rfid:demo:location1");
                            ex.setReadPoint("urn:cuhk:rfid:demo:readpoint1");
                            ex.setEpcList(tagID);
                            epcisStatus = ceg.generateEvent(ex);
                            System.out.println("Done !!!!");
                        }
                       
                        boolean isNewTag=true;

                        // update individual view
                        tableModel= (DefaultTableModel) view.getTableModel();
                        tagVector = (Vector) tableModel.getDataVector();
                        
                        for (int row=0; row<tagVector.size(); row++) {
                            Vector tag = (Vector) tagVector.elementAt(row);
                            
                            if (tagID.equals((tag).elementAt(0))) {
                                viewRowId=row;
                                isNewTag=false;
                                tableModel.setValueAt(reportSet,row,1);
                                tableModel.setValueAt(reports.getDate(),row,2);
                                tableModel.setValueAt(view.getReaders(),row,3);
                                int history = ((Integer) tableModel.getValueAt(row,5)).intValue();
                                tableModel.setValueAt(0,row,5);
                                tableModel.setValueAt(epcisStatus,row,6);
                                tableModel.moveRow(row,row,0);
                                break;
                            }
                        }
                        
                        if (isNewTag) {
                            Object[] newRow = {tagID, reportSet, reports.getDate(), view.getReaders(), viewer.getDict().get(tagID), 0, epcisStatus};
                            tableModel.addRow(newRow);
                            tableModel.moveRow(tableModel.getRowCount()-1,tableModel.getRowCount()-1,0);
                            
                        }

                        // update main view
                        tableModel = (DefaultTableModel) viewer.getTableModel_Main();
                        tagVector = (Vector) tableModel.getDataVector();

                        isNewTag=true;
                        
                        for (int row=0; row<tagVector.size(); row++) {
                            Vector tag = (Vector) tagVector.elementAt(row);
                            
                            if (tagID.equals((tag).elementAt(0))) {
                                mainViewRowId=row;
                                isNewTag=false;
                                
                                //System.out.println("Column Count: " + tableModel.getColumnCount());
                                tableModel.setValueAt(reportSet,row,1);
                                tableModel.setValueAt(reports.getDate(),row,2);
                                tableModel.setValueAt(view.getReaders(),row,3);  
                                tableModel.setValueAt(epcisStatus,row,5);
                                break;
                            }
                        }
                        
                        if (isNewTag) {
                            Object[] newRow = {tagID, reportSet, reports.getDate(), view.getReaders(), viewer.getDict().get(tagID),epcisStatus};                                
                            tableModel.addRow(newRow);
                            
                        }
                        

                    }
                }
            }
            System.out.println("Reader: " + view.getReaders());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class SocketThrdServer {

    static int client_port=6666;
    
    ServerSocket server = null;
    Viewer viewer;
    
    SocketThrdServer(Viewer viewer) {
        this.viewer=viewer;
    }
    
    public void listenSocket(){
        try {
            server = new ServerSocket(client_port);
        } catch (IOException e) {
            this.viewer.getDebuger().log("Impossível abrir porta " + client_port);
        }
        while(true){
            ClientWorker w;
            try{
                w = new ClientWorker(server.accept(),viewer);
                Thread t = new Thread(w);
                t.start();
            } catch (IOException e) {
            	this.viewer.getDebuger().log("Accept falhou na porta " + client_port);
            }
        }
    }
    
    protected void finalize(){
//Objects created in run method are finalized when
//program terminates and thread exits
        try{
            server.close();
        } catch (IOException e) {
        	this.viewer.getDebuger().log("Impossível fechar o socket");
            System.exit(-1);
        }
    }
}
